#pragma once

#include "noncopyable.h"
#include "Thread.h"

#include <functional>
#include <string>
#include <vector>
#include <memory>
#include <atomic>
#include <mutex>

class EventLoop;
class EventLoopThread;

class EventLoopThreadPool : noncopyable
{
public:
  using ThreadInitCallback = std::function<void(EventLoop*)>;
public:
  EventLoopThreadPool(EventLoop *base, int numThreads, const std::string& name);
  ~EventLoopThreadPool() {}
  virtual void setThreadNum(int numThreads) { m_numThread = numThreads; }
  void start(const ThreadInitCallback& cb = ThreadInitCallback());
  virtual EventLoop* getNextLoop();
  virtual EventLoop* getNextLoop(const std::string& key);
  std::vector<EventLoop*> getAllLoop();
  bool started() const { return m_started; }
  std::string getName() const { return m_name; }
protected:
  EventLoop *m_baseLoop; // EventLoop 
  std::string m_name;
  int m_numThread;
  int m_next;
  bool m_started; 
  std::vector<std::unique_ptr<EventLoopThread>> m_threads;
  std::vector<EventLoop*> m_loops;
};

class DynamicEventLoopThreadPool : noncopyable
{
public:
  using ThreadInitCallback = std::function<void(EventLoop*)>; 
public:
  DynamicEventLoopThreadPool(EventLoop *base, int numThread, const std::string& name = "DynamicEventLoopThreadPool");
  virtual void setThreadNum(const int numThread);
  void start(const ThreadInitCallback& cb = ThreadInitCallback());
  virtual EventLoop* getNextLoop();
  virtual EventLoop* getNextLoop(const std::string& key);
  std::vector<EventLoop*> getAllLoop();
  bool started() const { return m_started; }
  std::string getName() const { return m_name; }
private:
  // 监控线程函数
  void monitoringThread();
  // 扩缩测率
  void adjustPoolSize();
  void expandPool(const int addNum);
  void shrinkPool(const int subNum);

  double getCpuUsage();
  int64_t getMemUsage();

  std::string buildName(const uint32_t index);
private:
  struct WorkerThread
  {
    // WorkerThread() = default;
    // ~WorkerThread() = default; 
    WorkerThread(EventLoopThread* thread, bool active)
      : m_thread(thread)
      , m_active(active)
    {}
    WorkerThread(WorkerThread&& worker)
    {
      m_thread = worker.m_thread;
      m_active.exchange(worker.m_active);
      worker.m_thread = nullptr;
    }
    WorkerThread& operator=(const WorkerThread& worker)
    {
      m_thread = worker.m_thread;
      m_active.exchange(worker.m_active);
      return *this;
    }
    EventLoopThread* m_thread;
    std::atomic<bool> m_active{true};
  };
  /**
   * 监控指标
   * 
   * 指标名称	采集方式	调整策略
   * CPU使用率	读取/proc/stat	>70%扩容，<30%缩容
   * 内存使用量	读取/proc/meminfo	>80%时停止扩容
   * 待处理任务数	各EventLoop队列长度求和	每500任务/线程扩容，每200任务/线程缩容
   * 平均响应延迟	请求处理时间戳差值	>100ms扩容，<50ms缩容
   */
  struct LoadMetrics
  {
    LoadMetrics() = default;
    ~LoadMetrics() = default;
    std::atomic<int64_t> m_pendingTasks {0}; // 待处理任务数
    std::atomic<double> m_cpuUsage {0}; // CPU使用率
    std::atomic<int64_t> m_avgLatency {0}; // 平均处理时延
  };
private:
  EventLoop *m_baseLoop;
  std::string m_name;
  std::atomic<bool> m_started;
  // 线程池控制
  std::atomic<int> m_minThread {0};
  std::atomic<int> m_maxThread {0};
  std::atomic<int> m_currentThread {0};
  
  std::vector<WorkerThread> m_workers;
  std::vector<EventLoop*> m_loops;

  mutable std::mutex m_mutex;
  
  // 负载指标
  LoadMetrics m_metrics;

  // 监控线程
  std::unique_ptr<Thread> m_monitorThread;
  std::atomic<bool> m_monitoring{false};

  // 线程初始化回调
  ThreadInitCallback m_threadInitCallback;

};